import AMap from 'AMap'
import { MAP_STYLE } from './amap-config'

// var xyzTileLayer = () => new AMap.TileLayer({
//   // 图块取图地址
//   getTileUrl: 'http://t{0,1,2,3,4,5,6,7}.tianditu.gov.cn/DataServer?T=vec_w&tk=89cd1623dd7336f91f85222d2022edae&x=[x]&y=[y]&l=[z]',
//   zIndex: 100
// });
//
// var wordTileLayer = () => new AMap.TileLayer({
//   // 图块取图地址
//   getTileUrl: 'http://t{0,1,2,3,4,5,6,7}.tianditu.gov.cn/DataServer?T=cva_w&tk=89cd1623dd7336f91f85222d2022edae&x=[x]&y=[y]&l=[z]',
//   zIndex: 101
// });

function noop() {}

class BaseMap {
  createGraphicsLayer() {
    return new AMap.OverlayGroup()
  }
  createClusterLayer() {
    return new AMap.MarkerClusterer(this.map)
    // , [], {
    //   renderClusterMarker(context) {
    //     const obj = MAP_STYLE[name] && MAP_STYLE[name]();
    //     context.marker.setContent(obj.content);
    //   }
    // }
  }
  createAMapWMSLayer(params) {
    return new AMap.TileLayer.WMS(params)
  }
}

export class MapContainer extends BaseMap {
  constructor(options) {
    super()
    this.options = Object.assign({}, options)
    this.graphicSelect = this.options.graphicSelect
    this._clickHook = this.options.clickHook || null
    this.layersMap = {}
    this.heatmapLayersMap = {}
    this.clusterLayersMap = {}
    this.WMSLayerMap = {}
    this.pupupNode = {}
    this.initMap()
  }
  initMap() {
    const map = new AMap.Map(
      this.options.target,
      Object.assign({
        zoom: this.options.zoom, // 级别
        center: this.options.center, // 中心点坐标
        // viewMode: '2D', //使用3D视图
        // layers: [xyzTileLayer(), wordTileLayer()],
        ...this.options
      })
    )
    this.infoWindow = new AMap.InfoWindow({
      offset: new AMap.Pixel(10, -30),
      closeWhenClickMap: this.options.closeWhenClickMap || false
    })
    this.infoWindow.on('close', () => {
      if (this.clickMarker) {
        this.clickMarker.hide()
      }
    })
    this.map = map
  }
  /**
   * 删除图层
   * @param {*} name 图层名称
   */
  clearLayer(name, type = 'graphicLayer') {
    const layer = this.getLayers(name)
    if (layer[type]) {
      layer[type].clearOverlays()
    }
  }
  /**
   * 获取图层
   * @param {any} name 图层名称
   * @param {*} type
   */
  getLayers(name = '', type = null, params) {
    if (type === 'heatmap') {
      if (this.heatmapLayersMap[name] === undefined) {
        this.heatmapLayersMap[name] = this.craeteHeatMapLayer(name)
      }
    } else if (type === 'cluster') {
      if (this.clusterLayersMap[name] === undefined) {
        this.clusterLayersMap[name] = this.createClusterLayer(name)
      }
    } else if (type === 'WMSLayer') {
      if (this.WMSLayerMap[name] === undefined) {
        this.WMSLayerMap[name] = this.createAMapWMSLayer(params)
      }
    } else {
      if (this.layersMap[name] === undefined) {
        this.layersMap[name] = this.createGraphicsLayer(name)
      }
    }
    return {
      graphicLayer: this.layersMap[name],
      clusterLayer: this.clusterLayersMap[name],
      heatmapLayer: this.heatmapLayersMap[name],
      WMSLayer: this.WMSLayerMap[name]
    }
  }
  /**
   * 添加点
   * @param {any} name 图层名称
   * @param {Array} points 点位数组
   * @param {*} type
   */
  addPoints(name, points, type = null, { selfHandleClick = null, ...options } = {}) {
    const layer = this.getLayers(name, type)
    const markers = []
    points.forEach(item => {
      // 创建点实例
      if (!/\d/.test(item.lon || item.longitude)) {
        return
      }
      if ((item.lon || item.longitude) && (item.lat || item.latitude)) {
        const mapStyle = MAP_STYLE[item.type || name] || {}
        const other = typeof mapStyle === 'function' ? mapStyle(item) : mapStyle
        var marker = new AMap.Marker({
          position: new AMap.LngLat(
            item.lon || item.longitude,
            item.lat || item.latitude
          ),
          // icon: MAP_STYLE[item.type || name],
          extData: { ...item, type: name },
          ...other
        })
        marker.on('click', selfHandleClick || this.markerClick.bind(this))
        markers.push(marker)
      }
    })
    if (type === 'cluster') {
      const { clusterLayer } = layer
      clusterLayer.clearMarkers()
      clusterLayer.setMaxZoom(options.maxZoom || 16)
      clusterLayer.addMarkers(markers)
    } else {
      layer.graphicLayer.clearOverlays()
      layer.graphicLayer.addOverlays(markers)
      this.map.add(layer.graphicLayer)
    }
  }
  addPolygon(name, path, { clickHook, ...options }) {
    const { graphicLayer } = this.getLayers(name, null)
    const layer = new AMap.Polygon({
      path,
      ...options
    })
    layer.on('click', clickHook || this._clickHook.bind(this))
    graphicLayer.clearOverlays()
    graphicLayer.addOverlays(layer)
    this.map.add(graphicLayer)
  }
  addGeoJSON(name, geoJSON, type = null, options) {
    const { graphicLayer } = this.getLayers(name, type)
    graphicLayer.clearOverlays()
    const geojson = new AMap.GeoJSON({
      geoJSON: geoJSON,
      ...options
    })
    graphicLayer.addOverlays(geojson)
    this.map.add(graphicLayer)
  }
  /**
   * 点位点击触发
   * @param {Event} e
   */
  markerClick(e) {
    const map = this
    const data = e.target.getExtData()
    this._clickHook && this._clickHook(map, e)
    this.graphicSelect &&
    this.graphicSelect(data, vm => {
      vm.$nextTick(() => {
        map.setPosition(vm.$refs[map.options.popup], e.target.getPosition())
      })
    })
  }
  /**
   * 手动添加地图弹框
   * @param {Element} dom DM对象
   * @param {Object} posit 经纬度
   */
  setPosition(dom, posit) {
    this.infoWindow.setContent(dom)
    this.infoWindow.open(this.map, posit)
  }
  setFitView(layer, config = { immediately: true, maxZoom: 10 }) {
    this.map.setFitView(layer, config)
  }
  destroy() {
    this.map.destroy()
    this.infoWindow = null
    this.graphicSelect = null
    this._clickHook = null
    this.layersMap = null
    this.heatmapLayersMap = null
    this.clusterLayersMap = null
    this.map = null
  }
  addWMSLayer(name, options) {
    const { graphicLayer } = this.getLayers(name, null)
    graphicLayer.clearOverlays()
    const WMSLayer = this.createAMapWMSLayer(options)
    graphicLayer.addOverlays(WMSLayer)
    this.map.add(graphicLayer)
  }
  /**
   * 绘制轨迹
   * @param {Array} track 轨迹数组
   * @param {Function} stopCallback 停止播放时的回调函数
   * @param {Object} polylineStyle 基础线的样式
   * @param {Object} passedPolylineStyle 动画线的样式
   */
  drawTrackOld(track, stopCallback, polylineStyle = {}, passedPolylineStyle = {}) {
    const marker = new AMap.Marker({
      map: this.map,
      position: track[0],
      // icon: TrackIconGreen,
      offset: new AMap.Pixel(-10, -10)
    })
    // 绘制轨迹
    const polyline = new AMap.Polyline({
      map: this.map,
      path: track,
      showDir: true,
      strokeColor: '#28F',
      // 线透明度
      // strokeOpacity: 1,
      // 线宽
      strokeWeight: 4,
      // 线样式
      // strokeStyle: "solid"
      ...polylineStyle
    })
    const passedPolyline = new AMap.Polyline({
      map: this.map,
      // path: lineArr,
      // 线颜色
      strokeColor: '#AF5',
      // 线透明度
      // strokeOpacity: 1,
      // 线宽
      strokeWeight: 4,
      // 线样式
      // strokeStyle: "solid"
      ...passedPolylineStyle
    })
    let movingFlag = false
    let stopTimer = null
    marker.on('moving', function(e) {
      passedPolyline.setPath(e.passedPath)
      movingFlag = true
      if (stopTimer) {
        clearTimeout(stopTimer)
      }
    })
    marker.on('moveend', function() {
      movingFlag = false
      stopTimer = setTimeout(() => {
        stopCallback(movingFlag)
      }, 200)
    })
    return {
      startAnimation() {
        marker.moveAlong(track, 20000)
      },
      pauseAnimation() {
        marker.pauseMove()
      },
      resumeAnimation() {
        marker.resumeMove()
      },
      stopAnimation() {
        marker.stopMove()
      },
      clearTrack() {
        marker.stopMove()
        marker.setMap(null)
        passedPolyline.setMap(null)
        polyline.setMap(null)
        stopCallback && stopCallback(false)
      }
    }
  }
  setCenterPosition(lnglat, zoom = this.map.getZoom()) {
    this.map.setZoomAndCenter(zoom, lnglat)
  }
  drawTrack(startPoint, stopCallback) {
    const marker = new AMap.Marker({
      map: this.map,
      position: startPoint,
      // icon: TrackIconGreen,
      offset: new AMap.Pixel(-10, -10)
    })

    const polyline = new AMap.Polyline({
      map: this.map,
      showDir: true,
      strokeColor: '#28F',
      // 线透明度
      // strokeOpacity: 1,
      // 线宽
      strokeWeight: 4
      // 线样式
      // strokeStyle: "solid"
      // ...polylineStyle
    })

    const passedPolyline = new AMap.Polyline({
      map: this.map,
      // path: lineArr,
      // 线颜色
      strokeColor: '#AF5',
      // 线透明度
      // strokeOpacity: 1,
      // 线宽
      strokeWeight: 4
      // 线样式
      // strokeStyle: "solid"
      // ...passedPolylineStyle
    })
    let stopTimer = null
    marker.on('moving', function() {
      // passedPolyline.setPath(e.passedPath)
      if (stopTimer) {
        clearTimeout(stopTimer)
      }
    })
    marker.on('moveend', function() {
      stopTimer = setTimeout(() => {
        stopCallback()
      }, 200)
    })

    return {
      polyline,
      passedPolyline,
      startAnimation(track, speed = 2000) {
        marker.moveAlong(track, speed)
      },
      pauseAnimation() {
        marker.pauseMove()
      },
      resumeAnimation() {
        marker.resumeMove()
      },
      stopAnimation() {
        marker.stopMove()
      },
      clearTrack() {
        marker.stopMove()
        marker.setMap(null)
        passedPolyline.setMap(null)
        polyline.setMap(null)
      }
    }
  }
  /**
   * 绘制正方形
   * @param {Array} track 轨迹数组
   * @param {Function} stopCallback 停止播放时的回调函数
   * @param {Object} polylineStyle 基础线的样式
   * @param {Object} passedPolylineStyle 动画线的样式
   */
  createMouseTool(callback = noop) {
    let mouseTool
    if (this.mouseTool) {
      return this.mouseTool
    } else {
      mouseTool = this.mouseTool = new AMap.MouseTool(this.map)
      AMap.event.addListener(mouseTool, 'draw', function(e) {
        callback(e)
      })
      return mouseTool
    }
  }
}
